function Game( canvas ) {
  this.canvas = canvas ;
  this.surface = canvas.getContext( '2d' ) ;
//  this.width = Number( canvas.getAttribute( 'width' ) ) - Game._SIDE_WIDTH ;
  this.width = Number( canvas.getAttribute( 'width' ) ) ;
  this.height = Number( canvas.getAttribute( 'height' ) ) ;

  var canvas = document.createElement( 'canvas' ) ;
  canvas.setAttribute( 'width', this.width ) ;
  canvas.setAttribute( 'height', this.height ) ;
  this.bgSurface = canvas.getContext( '2d' ) ;

  this.oldTime = null ;
  this.fps = null ;
  this.count = 0 ;

  this.state = 0 ;
  this.flags = 0 ;

  this.uri = './sample/' ;
  this._generatePage( 1 ) ;
}

Game._FPS = 60 ;
Game._FPS_SPAN = 60 ;

Game._FLAG_MESSAGE_STOP = 0x1 ;


Game.prototype.run = function( ) {
  this._runStep( ) ;
} ;


Game.prototype.clear = function( surface ) {
  surface.clearRect( 0, 0, this.width, this.height ) ;
} ;


Game.prototype.handleKeyDown = function( e ) {
  this.states[ this.state ].handleKeyDown( e ) ;
  e.preventDefault( ) ;
} ;


Game.prototype.handleKeyUp = function( e ) {
  this.states[ this.state ].handleKeyUp( e ) ;
  e.preventDefault( ) ;
} ;


Game.prototype.handleOnClick = function( e ) {
  var x = e.pageX - this.canvas.offsetLeft ;
  var y = e.pageY - this.canvas.offsetTop ;
  this.page.handleOnClick( e, x, y ) ;
} ;


Game.prototype.handleTouchStart = function( e ) {
  var t = e.touches[ 0 ] ;
  var x = t.pageX - this.canvas.offsetLeft ;
  var y = t.pageY - this.canvas.offsetTop ;
  this.page.handleOnClick( e, x, y ) ;
} ;


Game.prototype.notifyOptionSelect = function( id ) {
  this._generatePage( id ) ;
} ;


Game.prototype._generatePage = function( id ) {
  var xhr = new XMLHttpRequest( ) ;
  xhr.open( 'GET', this.uri + id + '.txt', false ) ;
  xhr.send( null ) ;
  var params = JSON.parse( xhr.responseText ) ;
  this.page = new PageMessage( this, params.body, params.options ) ;
  this.clear( this.surface ) ;
} ;


Game.prototype._runStep = function( ) {
  this.page.runStep( ) ;
  this.page.display( this.surface ) ;
  this.count++ ;
  requestAnimationFrame( this._runStep.bind( this ) ) ;
} ;


Game.prototype._calculateFps = function( ) {
  if( ( this.count % Game._FPS_SPAN ) != 0 )
    return ;
  var newTime = Date.now( ) ;
  if( this.oldTime ) {
    this.fps = parseInt( 1000 * Game._FPS_SPAN / ( newTime - this.oldTime ) ) ;
  }
  this.oldTime = newTime ;
} ;


Game.prototype._displayFps = function( surface ) {
  this._calculateFps( ) ;
  if( ! this.fps )
    return ;

  surface.save( ) ;
  surface.shadowColor = 'rgb( 255, 255, 255 )' ;
  surface.font = '16px Arial' ;
  surface.fillText( this.fps + 'fps',
                    this.getWidth( ) - 50,
                    this.getHeight( ) - 15 ) ;
  surface.restore( ) ;
} ;


Game.prototype.getWidth = function( ) {
  return this.width ;
} ;


Game.prototype.getHeight = function( ) {
  return this.height ;
} ;


Game.prototype.isFlagSet = function( type ) {
  return ( this.flags & type ) ? true : false ;
} ;


Game.prototype.setFlag = function( type ) {
  this.flags |= type ;
} ;


Game.prototype.clearFlag = function( type ) {
  this.flags &= ~type ;
} ;
